package com.easytouch.vmhdl.animation;

import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.os.Build;
import android.os.Handler;
import android.widget.ImageView;

import java.lang.ref.SoftReference;

/**
 * Created by v_xiaoziqiang on 17/11/21.
 */

public class FramesAnimation {

    private int[] mFrames; // 帧数组
    private int mIndex; // 当前帧
    private boolean mOneShot; // 是否只播放一次
    private boolean mShouldRun; // 开始/停止播放用
    private boolean mIsRunning; // 动画是否正在播放，防止重复播放
    private SoftReference<ImageView> mSoftReferenceImageView; // 软引用ImageView，以便及时释放掉
    private Handler mHandler;
    private int mDelayMillis;

    private Bitmap mBitmap = null;
    private BitmapFactory.Options mBitmapOptions;//Bitmap管理类，可有效减少Bitmap的OOM问题

    public FramesAnimation(ImageView imageView, TypedArray array, int fps, boolean oneShot) {
        mHandler = new Handler();
        mFrames = getData(array);
        mIndex = -1;
        mOneShot = oneShot;
        mSoftReferenceImageView = new SoftReference<ImageView>(imageView);
        mShouldRun = false;
        mIsRunning = false;
        mDelayMillis = 1000 / fps;//帧动画时间间隔，毫秒

        imageView.setImageResource(mFrames[0]);

        // 当图片大小类型相同时进行复用，避免频繁GC
        if (Build.VERSION.SDK_INT >= 11) {
            Bitmap bmp = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
            int width = bmp.getWidth();
            int height = bmp.getHeight();
            Bitmap.Config config = bmp.getConfig();
            mBitmap = Bitmap.createBitmap(width, height, config);
            mBitmapOptions = new BitmapFactory.Options();
            //设置Bitmap内存复用
            mBitmapOptions.inBitmap = mBitmap;//Bitmap复用内存块，类似对象池，避免不必要的内存分配和回收
            mBitmapOptions.inMutable = true;//解码时返回可变Bitmap
            mBitmapOptions.inSampleSize = 1;//缩放比例
        }
    }

    //循环读取下一帧
    private int getNext() {
        mIndex++;
        if (mIndex >= mFrames.length) {
            if (mOneShot) {
                mShouldRun = false;
                mIndex--;
            } else {
                mIndex = 0;
            }
        }
        return mFrames[mIndex];
    }

    /**
     * 播放动画，同步锁防止多线程读帧时，数据安全问题
     */
    public synchronized void start() {
        mShouldRun = true;
        if (mIsRunning)
            return;

        Runnable runnable = new Runnable() {
            @Override
            public void run() {

                ImageView imageView = mSoftReferenceImageView.get();
                if (!mShouldRun || imageView == null) {
                    mIsRunning = false;
                    return;
                }

                mIsRunning = true;
                //新开线程去读下一帧
                mHandler.postDelayed(this, mDelayMillis);

                if (imageView.isShown()) {
                    int imageRes = getNext();
                    if (mBitmap != null) { // so Build.VERSION.SDK_INT >= 11
                        Bitmap bitmap = null;
                        try {
                            bitmap = BitmapFactory.decodeResource(imageView.getResources(), imageRes, mBitmapOptions);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        if (bitmap != null) {
                            imageView.setImageBitmap(bitmap);
                        } else {
                            imageView.setImageResource(imageRes);
                            mBitmap.recycle();
                            mBitmap = null;
                        }
                    } else {
                        imageView.setImageResource(imageRes);
                    }
                }

            }
        };

        mHandler.post(runnable);
    }

    /**
     * 停止播放
     */
    public synchronized void stop() {
        mShouldRun = false;
    }


    private int[] getData(TypedArray array) {
        int len = array.length();
        int[] intArray = new int[array.length()];

        for (int i = 0; i < len; i++) {
            intArray[i] = array.getResourceId(i, 0);
        }
        array.recycle();
        return intArray;
    }
}
